package com.xuecheng.teaching.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.teaching.model.dto.CourseWorkRecDTO;
import com.xuecheng.api.teaching.model.dto.CourseWorkRecordDTO;
import com.xuecheng.api.teaching.model.dto.RecGroupDTO;
import com.xuecheng.api.teaching.model.dto.WorkRecordDTO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.TeachPlanEnum;
import com.xuecheng.common.enums.teaching.WorkRecordCorrectionStatusEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.teaching.common.constant.TeachingErrorCode;
import com.xuecheng.teaching.convert.CourseWorkConvert;
import com.xuecheng.teaching.convert.WorkRecordConvert;
import com.xuecheng.teaching.entity.CourseWorkRec;
import com.xuecheng.teaching.entity.Work;
import com.xuecheng.teaching.entity.WorkRecord;
import com.xuecheng.teaching.mapper.WorkRecordMapper;
import com.xuecheng.teaching.service.CourseWorkRecService;
import com.xuecheng.teaching.service.WorkRecordService;
import com.xuecheng.teaching.service.WorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


/**
 * <p>
 * 作业提交记录 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class WorkRecordServiceImpl extends ServiceImpl<WorkRecordMapper, WorkRecord> implements WorkRecordService {


    @Autowired
    private CourseWorkRecService courseWorkRecService;

    @Autowired
    private WorkRecordService workRecordService;

    @Autowired
    private WorkService workService;

    /**
     * 批阅作业
     *
     * @param workRecordDTO
     * @return
     */
    @Override
    @Transactional
    public WorkRecordDTO correctionCourseWork(WorkRecordDTO workRecordDTO) {

        //1.根据id查询作业记录信息
        Long workRecordId = workRecordDTO.getWorkRecordId();

        WorkRecord workRecord = this.getById(workRecordId);

        if (ObjectUtils.isEmpty(workRecord)) {
            ExceptionCast.cast(TeachingErrorCode.E_130407);
        }

        //2.判断作业的状态
        String status = workRecord.getStatus();

        if (!(ObjectUtils.nullSafeEquals(WorkRecordCorrectionStatusEnum.RECORD_CORRECT_PENDING.getCode(), status))) {
            ExceptionCast.cast(TeachingErrorCode.E_130403);
        }

        //3.修改作业的批改状态
        workRecord.setStatus(WorkRecordCorrectionStatusEnum.RECORD_CORRECT_PENDED.getCode());

        //4.更新作业批阅的信息
        boolean result = this.updateById(workRecord);
        if (!result) {
            ExceptionCast.cast(TeachingErrorCode.E_130404);
        }


        LambdaQueryWrapper<CourseWorkRec> courseWorkRecLambdaQueryWrapper = new LambdaQueryWrapper<>();
        courseWorkRecLambdaQueryWrapper.eq(CourseWorkRec::getCoursePubId, workRecord.getCoursePubId());

        CourseWorkRec courseWorkRec = courseWorkRecService.getOne(courseWorkRecLambdaQueryWrapper);

        if (courseWorkRec.getTobeReviewed() > CommonEnum.DELETE_FLAG.getCodeInt()) {
            LambdaUpdateWrapper<CourseWorkRec> courseWorkRecLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            courseWorkRecLambdaUpdateWrapper.eq(CourseWorkRec::getCoursePubId, workRecord.getCoursePubId());

            courseWorkRecLambdaUpdateWrapper.set(CourseWorkRec::getTobeReviewed, courseWorkRec.getTobeReviewed() - CommonEnum.USING_FLAG.getCodeInt());

            boolean updateResult = courseWorkRecService.update(courseWorkRecLambdaUpdateWrapper);
            if (!updateResult) {
                ExceptionCast.cast(TeachingErrorCode.E_130409);
            }
        }


        LambdaUpdateWrapper<WorkRecord> workRecordLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        workRecordLambdaUpdateWrapper.eq(WorkRecord::getCoursePubId, workRecord.getCoursePubId());
        workRecordLambdaUpdateWrapper.eq(WorkRecord::getId,workRecord.getId());
        workRecordLambdaUpdateWrapper.set(WorkRecord::getCorrectComment, workRecordDTO.getCorrectComment());

        boolean workUpdateResult = this.update(workRecordLambdaUpdateWrapper);
        if (!workUpdateResult) {
            ExceptionCast.cast(TeachingErrorCode.E_130409);
        }


        WorkRecordDTO dto = CourseWorkConvert.INSTANCE.entity2DTO(workRecord);

        return dto;
    }


    /**
     * 根据作业id查询作业详情
     *
     * @param courseWorkId
     * @param companyId
     * @return
     */
    @Override
    public CourseWorkRecordDTO queryCourseWorkRecById(Long courseWorkId, Long companyId) {

        //判断数据合法性
        if (ObjectUtils.isEmpty(courseWorkId) || ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }

        CourseWorkRec courseWorkRec = courseWorkRecService.getById(courseWorkId);

        if (ObjectUtils.isEmpty(courseWorkRec)) {
            ExceptionCast.cast(TeachingErrorCode.E_130407);
        }

        CourseWorkRecDTO courseWorkRecDTO = CourseWorkConvert.INSTANCE.entity2dto(courseWorkRec);


        LambdaQueryWrapper<WorkRecord> workRecordQueryWrapper = new LambdaQueryWrapper<>();
        workRecordQueryWrapper.eq(WorkRecord::getCoursePubId, courseWorkRec.getCoursePubId());
        int count = workRecordService.count(workRecordQueryWrapper);


        int committerNumberCount = workRecordService.count(workRecordQueryWrapper);

        List<WorkRecord> workRecord = workRecordService.getBaseMapper().selectList(workRecordQueryWrapper);

        if (ObjectUtils.isEmpty(workRecord)) {
            ExceptionCast.cast(TeachingErrorCode.E_130407);
        }




        CourseWorkRecordDTO courseWorkRecordDTO = new CourseWorkRecordDTO();
        courseWorkRecordDTO.setCoursePubId(courseWorkRec.getCoursePubId());
        courseWorkRecordDTO.setAnswerNumber(courseWorkRecDTO.getAnswerNumber());
        courseWorkRecordDTO.setCommitedTime(courseWorkRecDTO.getCommitedTime());
        courseWorkRecordDTO.setCompanyId(companyId);
        courseWorkRecordDTO.setCompanyName(courseWorkRecDTO.getCompanyName());
        courseWorkRecordDTO.setCourseName(courseWorkRecDTO.getCourseName());
        courseWorkRecordDTO.setCourseWorkId(courseWorkId);
        courseWorkRecordDTO.setReviewedTime(courseWorkRecDTO.getReviewedTime());
        courseWorkRecordDTO.setTobeReviewed(courseWorkRecDTO.getTobeReviewed());
        courseWorkRecordDTO.setLearnerNumber(count);
        courseWorkRecordDTO.setCommitterNumber(committerNumberCount);
        courseWorkRecordDTO.setWorkNumber(count);


        ArrayList<RecGroupDTO> recGroupDTOs = new ArrayList<>();

        ArrayList<String> list = new ArrayList<>();
        for (WorkRecord record : workRecord) {
            String teachplanName = record.getTeachplanName();
            if (list.size() != 0) {
                for (String str : list) {
                    int size = list.size();
                    if (str.equals(teachplanName)){
                        break;
                    }else if (!list.get(size-1).equals(teachplanName)){
                        list.add(teachplanName);
                        break;
                    }
                }
            }else {
                list.add(teachplanName);
            }
        }

        for (String str : list) {
            workRecordQueryWrapper =new LambdaQueryWrapper<>();
            workRecordQueryWrapper.eq(WorkRecord::getCoursePubId, courseWorkRec.getCoursePubId());
            workRecordQueryWrapper.eq(WorkRecord::getTeachplanName, str);
            List<WorkRecord> workRecords = workRecordService.getBaseMapper().selectList(workRecordQueryWrapper);
            WorkRecord record = new WorkRecord();
            RecGroupDTO recGroupDto = new RecGroupDTO();
            if(!ObjectUtils.isEmpty(workRecords)){
                record = workRecords.get(0);
                recGroupDto.setCoursePubId(record.getCoursePubId().intValue());
                List<WorkRecordDTO> workRecordDTOList = CourseWorkConvert.INSTANCE.entitys2DTOs(workRecords);
                recGroupDto.setWorkRecordList(workRecordDTOList);
                recGroupDto.setTeachplanName(record.getTeachplanName());
            }
            recGroupDTOs.add(recGroupDto);
        }

        courseWorkRecordDTO.setRecGroupDTOList(recGroupDTOs);

        return courseWorkRecordDTO;

    }


    @Transactional
    public void submission(long id, String username) {


        LambdaQueryWrapper<WorkRecord> workRecordQueryWrapper = new LambdaQueryWrapper<>();
        workRecordQueryWrapper.eq(WorkRecord::getId, id);
        workRecordQueryWrapper.eq(WorkRecord::getUsername, username);
        WorkRecord workRecord = this.getOne(workRecordQueryWrapper);
        if (ObjectUtils.isEmpty(workRecord)) {

            ExceptionCast.cast(TeachingErrorCode.E_130407);

        }
        String status = workRecord.getStatus();
        Integer firstLevel = TeachPlanEnum.FIRST_PARENTID_FLAG;
        if (!(firstLevel.toString().equals(status))) {
            ExceptionCast.cast(TeachingErrorCode.E_130408);
        }

        LambdaUpdateWrapper<WorkRecord> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(WorkRecord::getId, id);
        updateWrapper.eq(WorkRecord::getUsername, username);
        updateWrapper.set(WorkRecord::getStatus, TeachPlanEnum.FIRST_LEVEL.toString());
        boolean update = this.update(updateWrapper);

        if (!update) {
            ExceptionCast.cast(TeachingErrorCode.E_130411);
        }

        //createCourseWorkRec(id, username);
    }



    private void createCourseWorkRec(long id, String username) {
        LambdaQueryWrapper<WorkRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkRecord::getId, id);
        queryWrapper.eq(WorkRecord::getUsername, username);
        WorkRecord workRecord = this.getOne(queryWrapper);

        LambdaQueryWrapper<Work> workQueryWrapper = new LambdaQueryWrapper<>();

        workQueryWrapper.eq(Work::getId, workRecord.getWorkId());
        Work work = workService.getOne(workQueryWrapper);
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkRecord::getCoursePubId, work.getCoursePubId());
        int count = this.count(queryWrapper);

        LambdaQueryWrapper<CourseWorkRec> courseWorkRecQueryWrapper = new LambdaQueryWrapper<>();
        courseWorkRecQueryWrapper.eq(CourseWorkRec::getCoursePubId, workRecord.getCoursePubId());
        CourseWorkRec courseWorkRec = courseWorkRecService.getOne(courseWorkRecQueryWrapper);
        if (ObjectUtils.isEmpty(courseWorkRec)) {
            courseWorkRec = new CourseWorkRec();
            courseWorkRec.setCoursePubId(workRecord.getCoursePubId());
            courseWorkRec.setCourseName(work.getCourseName());
            courseWorkRec.setCompanyId(work.getCompanyId());
            courseWorkRec.setWorkNumber(count);
            courseWorkRec.setAnswerNumber(1);
            courseWorkRec.setTobeReviewed(1);
            courseWorkRec.setCommitedTime(LocalDateTime.now());
            boolean save = courseWorkRecService.save(courseWorkRec);
            if (!save) {
                courseWorkRecService.save(courseWorkRec);
            }
        } else {
            LambdaUpdateWrapper<CourseWorkRec> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(CourseWorkRec::getId, courseWorkRec.getId());
            updateWrapper.set(CourseWorkRec::getWorkNumber, count);
            updateWrapper.set(CourseWorkRec::getAnswerNumber, courseWorkRec.getAnswerNumber() + 1);
            updateWrapper.set(CourseWorkRec::getTobeReviewed, courseWorkRec.getTobeReviewed() + 1);
            updateWrapper.set(CourseWorkRec::getCommitedTime, LocalDateTime.now());
            boolean update = courseWorkRecService.update(updateWrapper);
            if (!update) {
                ExceptionCast.cast(TeachingErrorCode.E_130409);
            }
        }

    }

    @Override
    @Transactional
    public WorkRecordDTO createWorkRecord(WorkRecordDTO dto, String username) {

        WorkRecord workRecord = WorkRecordConvert.INSTANCE.dto2entity(dto);
        if (ObjectUtils.isEmpty(workRecord)) {
            ExceptionCast.cast(TeachingErrorCode.E_130408);
        }

        LambdaQueryWrapper<WorkRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkRecord::getWorkId, workRecord.getWorkId());
        queryWrapper.eq(WorkRecord::getUsername, username);
        WorkRecord record = this.getOne(queryWrapper);

        Work work = workService.getById(workRecord.getWorkId());
        String code = WorkRecordCorrectionStatusEnum.RECORD_CORRECT_PENDING.getCode();
        if (ObjectUtils.isEmpty(record)) {

            workRecord.setStatus(code);
            workRecord.setQuestion(work.getQuestion());
            workRecord.setTeachplanId(work.getTeachplanId());
            workRecord.setTeachplanName(work.getTeachplanName());
            workRecord.setUsername(username);
            workRecord.setCreateDate(null);
            boolean save = this.save(workRecord);
            if (!save) {
                ExceptionCast.cast(TeachingErrorCode.E_130409);
            }
            createCourseWorkRec(workRecord.getId(), username);
        } else {


            code = WorkRecordCorrectionStatusEnum.RECORD_CORRECT_PENDED.getCode();
            if (code.equals(record.getStatus())){
                ExceptionCast.cast(TeachingErrorCode.E_130413);
            }

            LambdaUpdateWrapper<WorkRecord> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(WorkRecord::getWorkId, workRecord.getWorkId());
            updateWrapper.eq(WorkRecord::getUsername, username);
            updateWrapper.eq(WorkRecord::getStatus, code);
            updateWrapper.set(WorkRecord::getAnswer, workRecord.getAnswer());
            updateWrapper.set(WorkRecord::getChangeDate, LocalDateTime.now());
            boolean update = this.update(updateWrapper);
            if (!update) {
                ExceptionCast.cast(TeachingErrorCode.E_130413);
            }
        }
        record = this.getOne(queryWrapper);

        return WorkRecordConvert.INSTANCE.entity2dto(record);
    }
}
